﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace System.Collections.Generic
{
	public static class MoreEnumerableExtensions
	{

		public static TValue Second<TValue>( this IEnumerable<TValue> list )
		{
			return list.Skip( 1 ).First();
		}

		public static TValue SecondOrDefault<TValue>( this IEnumerable<TValue> list )
		{
			return list.Skip( 1 ).FirstOrDefault();
		}

		public static TValue Third<TValue>( this IEnumerable<TValue> list )
		{
			return list.Skip( 2 ).First();
		}

		public static TValue ThirdOrDefault<TValue>( this IEnumerable<TValue> list )
		{
			return list.Skip( 2 ).FirstOrDefault();
		}

		/// <summary>
		/// Retorna true se existir somente um item na lista que safifaz <paramref name="predicate"/>
		/// </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <param name="list"></param>
		/// <param name="predicate"></param>
		/// <returns></returns>
		public static bool HasOnlyOne<TValue>( this IEnumerable<TValue> list, Func<TValue, bool> predicate )
		{
			return list.Where( predicate ).HasOnlyOne();
		}

		public static bool HasOnlyOne<TValue>( this IEnumerable<TValue> list )
		{
			return list.Count() == 1;
		}

		/// <summary>
		/// Percorre toda a <paramref name="list"/> executando a ação <paramref name="actionToTake"/>
		/// para cada item da lista
		/// </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <param name="list"></param>
		/// <param name="actionToTake"></param>
		public static void Each<TValue>( this IEnumerable<TValue> list, Action<TValue> actionToTake )
		{
			if ( list != null && actionToTake != null )
				foreach ( var item in list )
					actionToTake( item );
		}

		/// <summary>
		/// Realiza a execução da ação <paramref name="actionToTake"/> até que a condição <paramref name="condition"/> seja igual 'false'
		/// </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <param name="list"></param>
		/// <param name="condition"></param>
		/// <param name="actionToTake"></param>
		public static void DoWhile<TValue>( this IEnumerable<TValue> list, Predicate<TValue> condition, Action<TValue> actionToTake )
		{
			if ( list != null )
			{
				IEnumerator<TValue> iterator = list.GetEnumerator();
				while ( iterator.MoveNext()
					 && condition( iterator.Current ) )
				{
					actionToTake( iterator.Current );
				}
			}
		}

		/// <summary>
		/// Executa a função <paramref name="actionToTake"/> enquanto ela retornar 'true'
		/// </summary>
		/// <typeparam name="TValue"></typeparam>
		/// <param name="list"></param>
		/// <param name="actionToTake"></param>
		public static void DoWhile<TValue>( this IEnumerable<TValue> list, Func<TValue, bool> actionToTake )
		{
			if ( list != null )
			{
				IEnumerator<TValue> iterator = list.GetEnumerator();
				while ( iterator.MoveNext() && actionToTake( iterator.Current ) ) 
					;
			}
		}
	}
}
